package com.liuzy.crawler.pool;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import com.liuzy.crawler.Config;
import com.liuzy.crawler.core.FileSave;
import com.liuzy.crawler.core.Logger;
import com.liuzy.crawler.core.StringQueue;
import com.liuzy.crawler.util.FileUtil;

/**
 * 图片文件池
 * 
 * @author liuzy
 * @since 2015年9月17日
 */
public class DownLoadPool {
	private String downloadPath;
	private StringQueue queue;
	private boolean isRun = true;
	private List<Thread> threadList = new ArrayList<>();
	private int threadCount;

	private static AtomicInteger workingCount = new AtomicInteger(0);
	private static AtomicInteger success = new AtomicInteger(0);
	private static AtomicInteger cancel = new AtomicInteger(0);
	private static AtomicInteger fail = new AtomicInteger(0);

	public DownLoadPool(String output, int maxDownload, int threadCount) {
		this.downloadPath = FileUtil.creteDir(output);
		this.queue = new StringQueue(maxDownload);
		this.threadCount = threadCount;
	}

	public void add(String url) {
		if (isRun) {
			queue.add(url);
		}
	}

	public void startup() {
		try {
			for (int i = 0; i < threadCount; i++) {
				Thread thread = new Thread(new Runnable() {
					public void run() {
						while (isRun) {
							String url = queue.get();
							if (url == null) {
								try {
									Thread.sleep(100);
								} catch (Exception e) {
									e.printStackTrace();
								}
							} else {
								workingCount.getAndIncrement();
								String fileName = FileUtil.buildFileName(url);
								String saveDir;
								if (Config.dlBysite) {
									String siteName = url.substring(0, url.indexOf("/"));
									saveDir = FileUtil.creteDir(downloadPath + siteName + File.separator);
								} else {
									saveDir = downloadPath + fileName;
								}
								FileSave fileSave = new FileSave(url, saveDir, fileName);
								int status = fileSave.saveImage();
								switch (status) {
								case 0:
									success.getAndIncrement();
									break;
								case 1:
								case 2:
								case 3:
									cancel.getAndIncrement();
									break;
								case 4:
									fail.getAndIncrement();
									break;
								default:
									break;
								}
								Logger.dlLog(status, fileName);
								workingCount.getAndDecrement();
							}
						}
					}
				});
				thread.setName("DownLoadPool-thread-" + i);
				thread.start();
				threadList.add(thread);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@SuppressWarnings("deprecation")
	public void shutdown() {
		queue.clear();
		isRun = false;
		for (Thread thread : threadList) {
			thread.stop();
		}
	}

	public int[] getStatus() {
		int[] queueStatus = queue.getStatus();
		int[] status = { queueStatus[0], queueStatus[1], queueStatus[2], queueStatus[3], workingCount.get(), cancel.get(), fail.get(), success.get() };
		return status;
	}

	@Override
	public String toString() {
		return "[DownLoadPool]\t" + queue.toString() + "\tw:" + workingCount.get();
	}

	public boolean isFree() {
		return workingCount.get() == 0;
	}

}
